/*
 * Copyright (c) 2025 Huawei Technologies Co., Ltd.
 * openFuyao is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

// 程序入口
package main

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"env-check/pkg/clean"
	"env-check/pkg/config"
	"env-check/pkg/logger"
	"env-check/pkg/output"
	"env-check/pkg/program"
	"env-check/pkg/query"
)

// Application 主应用结构体
type Application struct {
	config *config.AppConfig
	logger *logger.Logger
}

// NewApplication 创建应用实例
func NewApplication(cfg *config.AppConfig, log *logger.Logger) *Application {
	if cfg == nil || log == nil {
		return nil
	}

	return &Application{
		config: cfg,
		logger: log,
	}
}

// Run 运行应用
func (app *Application) Run() error {
	app.logger.Info("envCheck tool start")
	app.logger.Info(fmt.Sprintf("mode: %s", app.config.Mode))

	var result string
	var outputFilename string

	// 根据模式执行不同操作
	switch app.config.Mode {
	case config.ModeQuery:
		result, outputFilename = app.executeQuery()
	case config.ModeClean:
		result, outputFilename = app.executeClean()
	case config.ModeProgramCheck:
		result, outputFilename = app.executeProgramCheck()
	default:
		return fmt.Errorf("unsupported: %s", app.config.Mode)
	}

	// 输出结果到控制台
	fmt.Println(result)

	// 保存结果到文件（如果需要）
	if outputFilename != "" {
		if err := app.saveResultToFile(outputFilename, result); err != nil {
			app.logger.Error("save result file failed: " + err.Error())
		} else {
			app.logger.Info("Results have been saved to: " + outputFilename)
		}
	}

	app.logger.Info("completed")
	return nil
}

// executeQuery 执行查询操作
func (app *Application) executeQuery() (string, string) {
	q := query.NewQuery(app.config, app.logger)
	result, err := q.Execute()
	if err != nil {
		app.logger.Error("file query failed: " + err.Error())
		return "", ""
	}

	// 格式化输出结果
	formatter := output.NewFormatter()
	outputStr, err := formatter.FormatQuery(result, app.config.OutputFormat)
	if err != nil {
		app.logger.Error("format the output failed: " + err.Error())
		return "", ""
	}

	// 确定输出文件名
	outputFile := app.getOutputFilename("query-result")
	return outputStr, outputFile
}

// executeClean 执行清理操作
func (app *Application) executeClean() (string, string) {
	c := clean.NewCleaner(app.config, app.logger)
	result, err := c.Execute()
	if err != nil {
		app.logger.Error("file clean failed: " + err.Error())
		return "", ""
	}

	// 格式化输出结果
	formatter := output.NewFormatter()
	outputStr, err := formatter.FormatClean(result, app.config.OutputFormat)
	if err != nil {
		app.logger.Error("format the output failed: " + err.Error())
		return "", ""
	}

	// 确定输出文件名
	outputFile := app.getOutputFilename("clean-result")
	return outputStr, outputFile
}

// executeProgramCheck 执行程序检查操作
func (app *Application) executeProgramCheck() (string, string) {
	p := program.NewProgramChecker(app.config, app.logger)
	result, err := p.Execute()
	if err != nil {
		app.logger.Error("program check failed: " + err.Error())
		return "", ""
	}

	if result.Summary.TotalInstalled > 0 {
		var installed []string
		for _, prog := range result.Programs {
			if prog.Installed {
				installed = append(installed, prog.Name)
			}
		}
		app.logger.Warning("detected installed application(s)： " + strings.Join(installed, ", ") + " please uninstall it yourself")
	}

	// 格式化输出结果
	formatter := output.NewFormatter()
	outputStr, err := formatter.FormatProgramCheck(result, app.config.OutputFormat)
	if err != nil {
		app.logger.Error("format the output failed: " + err.Error())
		return "", ""
	}

	// 确定输出文件名
	outputFile := app.getOutputFilename("program-check-result")
	return outputStr, outputFile
}

// getOutputFilename 生成输出文件名
func (app *Application) getOutputFilename(baseName string) string {
	// 只有 JSON 或 CSV 格式才保存到文件
	if app.config.OutputFormat == "json" || app.config.OutputFormat == "csv" {
		return fmt.Sprintf("%s.%s", baseName, app.config.OutputFormat)
	}
	return ""
}

// saveResultToFile 保存结果到文件
func (app *Application) saveResultToFile(filename string, content string) error {
	// 确保目录存在
	dir := filepath.Dir(filename)
	if dir != "." && dir != "" {
		if err := os.MkdirAll(dir, config.DirectoryMode); err != nil {
			return fmt.Errorf("create result directory failed: %v", err)
		}
	}

	// 写入文件
	if err := os.WriteFile(filename, []byte(content), config.FileMode); err != nil {
		return fmt.Errorf("write to result file failed: %v", err)
	}

	return nil
}

func main() {

	// 加载配置
	cfg, err := config.LoadConfig()
	if err != nil {
		fmt.Printf("load configuration failed: %v\n", err)
		return
	}

	// 初始化日志器
	log := logger.NewLogger(cfg.LogFile)

	// 创建并运行应用
	app := NewApplication(cfg, log)
	if app == nil {
		fmt.Printf("create tool instance failed\n")
		return
	}
	if err := app.Run(); err != nil {
		log.Error("tool run failed: " + err.Error())
	}
}
